﻿Object.prototype.extend = function (object, override, overNull) {
    var extend = function (dest, source, _override, _overNull) {
        for (prop in source)
            if (((_override || typeof dest[prop] == "undefined") || (_overNull && dest[prop] == null)) && (!Object.isOriginal || !Object.isOriginal(prop)))
                dest[prop] = source[prop];
        return dest;
    }
    if (object && typeof (object) == "object")
        return extend.apply(this, [this, object, override != false, overNull]);
    return this;
};

String.prototype.extend({

    endsWith: function (s) {
        return (this.substr(this.length - s.length) == s);
    },

    startsWith: function (s) {
        return (this.substr(0, s.length) == s);
    },

    trimLeft: function () {
        return this.replace(/^\s*/, "");
    },

    trimRight: function () {
        return this.replace(/\s*$/, "");
    },

    trim: function () {
        return this.trimRight().trimLeft();
    },

    toLower: function () {
        return this.toLowerCase();
    },

    toUpper: function () {
        return this.toUpperCase();
    },

    toFirstUpper: function () {
        var s = "";
        alert(this[1]);
        for (var i = 0; i < this.length; i++) {
            if (i == 0) s += this[i].toUpperCase();
            else s += this[i].toLowerCase();
        }
        return s;
    },

    replaceAll: function (search, replace) {
        var regex = new RegExp(search, ["g"]);
        return this.replace(regex, replace);
    },

    repeat: function (times) {
        if (times > 0)
            return new Array(times + 1).join(this);
        return "";
    },

    format: function () {
        var s = this;
        for (var i = 0; i != arguments.length; i++)
            s = s.replaceAll("\\{" + i + "\\}", arguments[i]);
        return s;
    },

    isEmpty: function () {
        return this.trim() == "";
    },

    right: function (count, fill) {
        if (count == this.length)
            return this;
        if (count > this.length) {
            if (fill == null || fill == undefined || fill.isEmpty())
                return this;
            var s = this;
            while (s.length < count)
                s = fill.right(count - s.length) + s;
            return s;
        }
        if (count < this.length)
            return this.substr(this.length - count, count);
    },

    left: function (count, fill, reallength) {
        if (this.bytesCount() <= count)
            return this;
        var s = "";
        var fillLength = (fill ? fill.bytesCount() : 0);
        for (var i = 0; i < this.length; i++) {
            if ((s.bytesCount() + fillLength + String(this.charAt(i)).bytesCount()) <= count)
                s += String(this.charAt(i));
            else
                break;
        }
        return s + fill;
    },

    bytesCount: function () {
        return this.replace(/[^\x00-\xff]/g, "aa").length;
    },

    toJSONString: function () {
        var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"': '\\"',
            '\\': '\\\\'
        };
        if (/["\\\x00-\x1f]/.test(this)) {
            return '"' +
            this.replace(/([\x00-\x1f\\"])/g, function (a, b) {
                var c = m[b];
                if (c)
                    return c;
                c = b.charCodeAt();
                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
            }) +
            '"';
        }
        return '"' + this + '"';
    },

    parseJSON: function () {
        try {
            return eval('(' + this + ')');
        }
        catch (e) {
            return null;
        }
    },
    parseRegexp: function () {
        try {
            var i = this.lastIndexOf("/");
            if (this.startsWith("/") && i > 0)
                return new RegExp(this.slice(1, i), this.slice(i + 1, this.length));
            return new RegExp(this);
        } catch (e) { }
        return null;
    }
}, false);


Object.prototype.extend({

    toJSONString: function () {
        var a = [];
        for (var k in this) {
            if (!Object.isOriginal(k)) continue;
            var v = this[k];
            switch (typeof (v)) {
                case 'object':
                    if (v) if (typeof v.toJSONString === 'function') a.push(k.toJSONString() + ':' + v.toJSONString());
                    else a.push(k.toJSONString() + ':null');
                    break;
                case 'string':
                case 'number':
                case 'boolean':
                    a.push(k.toJSONString() + ':' + v.toJSONString());
                    break;
            }
        }
        return '{' + a.join(',') + '}';
    },

    isIn: function (array) {
        if (array instanceof Array)
            return array.indexOf(this) >= 0;
        return false;
    }
});

Function.prototype.extend({

    delegate: function (context) {
        var _this = this;
        return function () { return _this.apply(context, arguments); };
    },

    callback: function (method, beginMethod, context) {
        var _this = this;
        var o = context || this;
        return function () {
            if (beginMethod) beginMethod.apply(o, arguments);
            _this.apply(o, arguments);
            if (method) method.apply(o, arguments);
        };
    }
});

if (!Array.prototype.push) {
    function array_push() {
        for (var i = 0; i < arguments.length; i++)
            this[this.length] = arguments[i];
        return this.length;
    }
    Array.prototype.push = array_push;
}
if (!Array.prototype.pop) {
    function array_pop() {
        lastElement = this[this.length - 1];
        this.length = Math.max(this.length - 1, 0);
        return lastElement;
    }
    Array.prototype.pop = array_pop;
}

Array.prototype.extend({

    toJSONString: function () {
        var a = [];
        for (var i = 0; i < this.length; i++) {
            var v = this[i];
            switch (typeof (v)) {
                case "object":
                    if (v) if (typeof v.toJSONString === 'function') a.push(v.toJSONString());
                    else a.push("null");
                    break;
                case 'string':
                case 'number':
                case 'boolean':
                    a.push(v.toJSONString());
                    break;
            }
        }
        return '[' + a.join(',') + ']';
    },

    contains: function (value, ignoreCase) {
        for (var i = 0; i < this.length; i++) {
            if (this[i] == value) return true;
            if (ignoreCase == true && typeof (this[i]) == "string" && typeof (value) == "string" && String(this[i]).toLowerCase() == String(value).toLowerCase()) return true;
        }
        return false;
    },

    indexOf: function (o, p, value) {
        for (var i = 0; i < this.length; i++) {
            if (typeof (this[i]) == "object" && p) {
                if (!this[i][p]) continue;
                if (value && this[i][p] != value) continue;
                return i;
            }
            else {
                if (this[i] == o)
                    return i;
            }
        }
        return -1;
    },

    remove: function () {
        for (var i = 0; i < arguments.length; i++) {
            var index = this.indexOf(arguments[i]);
            if (index == -1)
                continue;
            this.splice(index, 1);
        }
    },

    removeEmpty: function () {
        for (var i = this.length - 1; i >= 0; i--) {
            if (Object.isNull(this[i]) || this[i] == "")
                this.splice(i, 1);
        }
        return this;
    },

    each: function (iterator, context) {
        var method = context ? iterator.createDelegate(context) : iterator;
        for (var i = 0, length = this.length; i < length; i++) {
            if (method(this[i], i) == false) break;
        }
    },

    last: function () {
        if (this.length <= 0) return null;
        return this[this.length - 1];
    },

    first: function () {
        if (this.length <= 0) return null;
        return this[0];
    }
});


Array.parse = function (object) {
    var array = [];
    if (object.length != undefined && object.length != null && typeof (object) != "string" && typeof (object.length) == "number") {
        if (object.length == 0) return array;
        for (var i = 0; i < object.length; i++)
            array.push(object[i]);
    }
    else if (!(object instanceof Function) && typeof (object) == "object") {
        var regexp = null;
        var includeFunction = false;
        if (arguments[1]) {
            if (arguments[1] instanceof RegExp)
                regexp = arguments[1];
            else
                regexp = new RegExp(pattern, "g");
        }
        if (arguments[2] && arguments[2] == true)
            includeFunction = true;
        for (var p in object) {
            if (object[p]) {
                if ((!includeFunction && object[p] instanceof Function) || (!object[p] || regexp.test(p))) continue;
                array.push(object[p]);
                array[p] = array.last();
            }
        }
    }
    else if (typeof (object) == "string" && arguments[1] && typeof (arguments[1]) == "string") {
        var a = object.split(arguments[1]);
        var removeBlanks = true;
        if (arguments[2] && arguments[2] == false)
            removeBlanks = false;
        for (var i = 0; i < a.length; i++) {
            if (!a[i] && removeBlanks) continue;
            array.push(a[i]);
        }
    }
    else {
        array.push(object);
    }
    return array;
};

Boolean.prototype.extend({

    toJSONString: function () {
        return String(this);
    }
});


Date.prototype.extend({

    toJSONString: function () {
        return '"' + this.format() + '"';
    },


    format: function (dateTimeFormat) {
        var formatString = dateTimeFormat || "yyyy-MM-dd hh:mm:ss";
        var matchYear = formatString.match(/(y+)/);
        var matchMonth = formatString.match(/(M+)/);
        var matchDate = formatString.match(/(d+)/);
        var matchHour = formatString.match(/(h+)/);
        var matchMinute = formatString.match(/(m+)/);
        var matchSecond = formatString.match(/(s+)/);
        if (matchYear)
            formatString = formatString.replace(matchYear[0], String(this.getFullYear()).right(matchYear[1].length, "0"));
        if (matchMonth)
            formatString = formatString.replace(matchMonth[0], String(this.getMonth() + 1).right(matchMonth[1].length, "0"));
        if (matchDate)
            formatString = formatString.replace(matchDate[0], String(this.getDate()).right(matchDate[1].length, "0"));
        if (matchHour)
            formatString = formatString.replace(matchHour[0], String(this.getHours()).right(matchHour[1].length, "0"));
        if (matchMinute)
            formatString = formatString.replace(matchMinute[0], String(this.getMinutes()).right(matchMinute[1].length, "0"));
        if (matchSecond)
            formatString = formatString.replace(matchSecond[0], String(this.getSeconds()).right(matchSecond[1].length, "0"));
        return formatString;
    },

    addDays: function (days) {
        this.setDate(this.getDate() + days);
        return this;
    },
    /**
    * 添加指定月数
    * @param {Number} months 要添加的月数
    */
    addMonths: function (/*Number*/months) {
        this.setMonth(this.getMonth() + months);
        return this;
    },
    /**
    * 添加指定年数
    * @param {Number} years 要添加的年数
    */
    addYears: function (/*Number*/years) {
        this.setYear(this.getFullYear() + years);
        return this;
    },
    /**
    * 添加指定小时数
    * @param {Number} hours 要添加的小时数
    */
    addHours: function (/*Number*/hours) {
        this.setHours(this.getHours() + hours);
        return this;
    },
    /**
    * 添加指定分钟数
    * @param {Number} hours 要添加的分钟数
    */
    addMinutes: function (/*Number*/minutes) {
        this.setMinutes(this.getMinutes() + minutes);
        return this;
    },
    /**
    * 添加指定秒钟数
    * @param {Number} hours 要添加的秒钟数
    */
    addSeconds: function (/*Number*/seconds) {
        this.setSeconds(this.getSeconds() + seconds);
        return this;
    },
    addTimes: function (times) {
        var time = this.getTime() + times;
        this.setTime(time);
        return this;
    }
});

